import Redis from 'ioredis';
import events from 'events';
import request from 'request';
import cluster from 'cluster';
import {
    PULL_WXTOKEN_FROM_REDIS,
    MASTER_REDIS_WX_TOKEN_OPTIONS,
    WX_TOKEN_
} from '../config/config';
import { exesql } from '../database/db';
import { sendLogToEmail } from '../controllers/logger';

/**
 * 主进程处理wxToken
 */
class MasterWxToken {
    constructor() {
        if (cluster.isMaster) {
            this.weiXinToken = this.weiXinToken.bind(this);
            this.reloadInit = this.reloadInit.bind(this);

            console.log(`MasterWxToken init`);
            this.initEventEmitterMap();

            this.STATE_PREFIX = '_state';
            this.eventEmitterMap = new Map();
            // 初始化redis
            this.wxTokenRedis = new Redis(MASTER_REDIS_WX_TOKEN_OPTIONS);
            this.wxTokenRedis.connect().then(function () {
                console.log("master redis is running");
            });
        }
    }

    async weiXinToken(req, res) {
        const appid = req.query.app_id;
        const secret = req.query.app_secret;
        const wechatId = parseInt(req.query.wechat_id,10);
        const workerId = req.query.worker_id;
        console.log(`[worker][${workerId}] 请求微信Token,参数:appid:${appid}, secret:${secret},wechatid:${wechatId}`);
        this.getWeiXinTokenQueue(appid, secret, wechatId, (token) => {
            res.json({ wechat_id: wechatId, access_token: token });
        });
    }

    // 获取微信token队列
    async getWeiXinTokenQueue(appid, secret, wechatid, cb) {
        // 队列处理
        this.eventEmitterMap.get(wechatid).once('end', cb);
        if (this.eventEmitterMap.get(wechatid + this.STATE_PREFIX) === 'ready') {
            this.eventEmitterMap.set(wechatid + this.STATE_PREFIX, 'pending');
            // 请求微信服务器获取token
            const data = await this.getWeiXinToken(appid, secret);
            const jsonData = JSON.parse(data);
            if (jsonData) {
                const accessToken = jsonData.access_token || '';
                const tokenItem = {
                    wechat_id:wechatid,
                    token: accessToken,
                    expire_time: Math.floor(new Date().getTime() / 1000) + (jsonData.expires_in ?jsonData.expires_in:0)
                }
                // FIXME:设置redis，以及通知worker进程更新数据
                this.wxTokenRedis.set(WX_TOKEN_+wechatid,JSON.stringify(tokenItem))
                this.notifyWorkers();

                console.info(`master wechatid:${wechatid}, 获取新的 accessToken:${accessToken}`);
                
                this.eventEmitterMap.get(wechatid).emit('end', accessToken);
                this.eventEmitterMap.set(wechatid + this.STATE_PREFIX, 'ready');
            }
        } else {
            this.eventEmitterMap.get(wechatid).emit('end', '');
            this.eventEmitterMap.set(wechatid + this.STATE_PREFIX, 'ready');
        }
    }

    /**
     * 获取微信Token
     * @param {公众号appid} appid 
     * @param {公众号secret} secret 
     */
    getWeiXinToken(appid, secret) {
        return new Promise(function (resolve) {
            const url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + appid + '&secret=' + secret;
            request(url, function (error, resp, json) {
                console.error(`获取${appid}对应的微信token失败,`, error,json);
                if (error) {
                    resolve('');
                } else {
                    resolve(json);
                }
            });
        });
    }

    // 通知其他工作进程更新Redis中的token
    notifyWorkers() {
        Object.keys(cluster.workers).forEach(function (id) {
            cluster.workers[id].send(PULL_WXTOKEN_FROM_REDIS);
        });
    }

    // 程序启动必须调用该函数
    async initEventEmitterMap() {
        const sql = 'SELECT `wechat_id`,`app_id`,`app_secret`,`host`,`company_name`,`device_name`,`device_type`,`template_id`,`bind_img_name` FROM  `wechat_manage`';
        try {
            const { err, result } = await exesql(sql, []);
            if (err) {
                sendLogToEmail('*****加载公众号信息异常****,' + err.stack);
                return;
            }
            if (result.length === 0) {
                sendLogToEmail('*****没有找到公众号配置信息****');
                return;
            }
            this.eventEmitterMap.clear();
            result.forEach(row => {
                if (!this.eventEmitterMap.has(row.wechat_id)) {
                    let eventEmitter = new events.EventEmitter();
                    eventEmitter.setMaxListeners(0);
                    this.eventEmitterMap.set(row.wechat_id, eventEmitter);
                    this.eventEmitterMap.set(row.wechat_id + this.STATE_PREFIX, 'ready');
                }
            });
            console.log(`[master]:加入公众号数量:${this.eventEmitterMap.size / 2}`);
        } catch (err) {
            sendLogToEmail('*****加载公众号信息异常****,' + err.stack);
        }
    }

    // 重新加载配置信息
    reloadInit(){
        this.initEventEmitterMap();
    }

}

export default new MasterWxToken();